package com.yaxin.flowable.utils;

import cn.hutool.core.convert.Convert;
import com.yaxin.flowable.core.FormConf;

import java.util.*;

/**
 * 流程表单工具类
 *
 * @author KonBAI
 * @createTime 2022/8/7 17:09
 */
public class ProcessFormUtils {

    private static final String CONFIG = "__config__";
    private static final String MODEL = "__vModel__";

    /**
     * 填充表单项内容
     *
     * @param formConf 表单配置信息
     * @param data 表单内容
     */
    public static void fillFormData(FormConf formConf, Map<String, Object> data) {
        if (data == null) {
            data = Collections.emptyMap();
        }

        // 情况一：没有表单结构（wf_deploy_form 没有、或 startEvent 无 formKey）
        // ——> 根据业务数据自动生成一套 Parser 认可的结构
        if (formConf.getFields() == null || formConf.getFields().isEmpty()) {
            List<Map<String, Object>> fields = new ArrayList<>();
            for (Map.Entry<String, Object> entry : data.entrySet()) {
                fields.add(buildFieldFromKV(entry.getKey(), entry.getValue()));
            }
            formConf.setFields(fields);
            return; // 已生成结构，直接返回
        }

        // 情况二：已有结构 ——> 按原逻辑把值填充进去
        for (Map<String, Object> field : formConf.getFields()) {
            recursiveFillField(field, data);
        }
    }

    @SuppressWarnings("unchecked")
    private static void recursiveFillField(final Map<String, Object> field, final Map<String, Object> data) {
        if (!field.containsKey(CONFIG)) {
            return;
        }
        Map<String, Object> configMap = (Map<String, Object>) field.get(CONFIG);
        if (configMap.containsKey("children")) {
            List<Map<String, Object>> childrens = (List<Map<String, Object>>) configMap.get("children");
            for (Map<String, Object> children : childrens) {
                recursiveFillField(children, data);
            }
        }
        String modelKey = Convert.toStr(field.get(MODEL));
        Object value = data.get(modelKey);
        if (value != null) {
            configMap.put("defaultValue", value);
        }
    }

    /** 根据 key/value 生成一个符合 Parser 的表单项（带 __config__ / __vModel__ / children） */
    private static Map<String, Object> buildFieldFromKV(String key, Object value) {
        // 组件选择：尽量贴合数据类型，Parser 更容易正确渲染
        String tag = "el-input";        // 默认输入框
        String dateType = null;         // el-date-picker 的 type
        Object defaultValue = value;

        if (value instanceof Boolean) {
            tag = "el-switch";
        } else if (value instanceof Number || isNumeric(value)) {
            tag = "el-input-number";
            // 保持数值型（不要转字符串），方便 Parser 正确展示
            defaultValue = toNumber(value);
        } else if (looksLikeDateTime(value)) {
            tag = "el-date-picker";
            dateType = isDateOnly(value) ? "date" : "datetime";
        }

        // __config__：Parser 依赖的核心结构
        Map<String, Object> config = new LinkedHashMap<>();
        config.put("label", key);                // 先用英文 key，当需要时可做中文映射
        config.put("showLabel", true);
        config.put("span", 24);
        config.put("defaultValue", defaultValue == null ? "" : defaultValue);
        config.put("tag", tag);                  // 很多 Parser 会用到
        config.put("children", new ArrayList<>()); // 一定给空数组，避免前端读 children 报错

        // 字段主体
        Map<String, Object> field = new LinkedHashMap<>();
        field.put("__config__", config);
        field.put("__vModel__", key);            // 递归填充时就靠它找值
        field.put("style", new HashMap<>());     // 占位，很多 Parser 会读取

        // 不同组件的常见属性（最小集）
        if ("el-input".equals(tag)) {
            field.put("placeholder", "");
            field.put("clearable", true);
        } else if ("el-input-number".equals(tag)) {
            field.put("controlsPosition", "");
            // 可按需设置 min/max/precision
        } else if ("el-switch".equals(tag)) {
            field.put("activeValue", true);
            field.put("inactiveValue", false);
        } else if ("el-date-picker".equals(tag)) {
            field.put("type", dateType != null ? dateType : "date");
            field.put("placeholder", "请选择日期");
            field.put("valueFormat", "date".equals(dateType) ? "yyyy-MM-dd" : "yyyy-MM-dd HH:mm:ss");
            // 可加 format: 与展示格式一致
        }

        return field;
    }

    /** 是否是数字字符串 */
    private static boolean isNumeric(Object v) {
        if (v == null) return false;
        String s = String.valueOf(v).trim();
        if (s.isEmpty()) return false;
        try {
            new java.math.BigDecimal(s);
            return true;
        } catch (Exception e) {
            return false;
        }
    }

    /** 转 Number（尽量不丢精度） */
    private static Number toNumber(Object v) {
        if (v instanceof Number) return (Number) v;
        try {
            return new java.math.BigDecimal(String.valueOf(v));
        } catch (Exception e) {
            return null;
        }
    }

    /** yyyy-MM-dd 或 yyyy-MM-dd HH:mm:ss */
    private static boolean looksLikeDateTime(Object v) {
        if (v == null) return false;
        String s = String.valueOf(v).trim();
        return s.matches("\\d{4}-\\d{2}-\\d{2}$") ||
            s.matches("\\d{4}-\\d{2}-\\d{2}\\s+\\d{2}:\\d{2}:\\d{2}$");
    }

    private static boolean isDateOnly(Object v) {
        if (v == null) return false;
        String s = String.valueOf(v).trim();
        return s.matches("\\d{4}-\\d{2}-\\d{2}$");
    }
}
